﻿namespace Hishop.Weixin.Pay
{
    using Hishop.Weixin.Pay.Domain;
    using Hishop.Weixin.Pay.Notify;
    using Hishop.Weixin.Pay.Util;
    using System;
    using System.IO;
    using System.Text;

    public class NotifyClient
    {
        private PayAccount _payAccount;
        public static readonly string Update_Feedback_Url = "https://api.weixin.qq.com/payfeedback/update";

        public NotifyClient(PayAccount account) : this(account.AppId, account.AppSecret, account.PartnerId, account.PartnerKey, account.PaySignKey)
        {
        }

        public NotifyClient(string appId, string appSecret, string partnerId, string partnerKey, string paySignKey)
        {
            PayAccount account = new PayAccount {
                AppId = appId,
                AppSecret = appSecret,
                PartnerId = partnerId,
                PartnerKey = partnerKey,
                PaySignKey = paySignKey
            };
            this._payAccount = account;
        }

        public AlarmNotify GetAlarmNotify(Stream inStream)
        {
            string xml = this.ReadString(inStream);
            return this.GetAlarmNotify(xml);
        }

        public AlarmNotify GetAlarmNotify(string xml)
        {
            if (string.IsNullOrEmpty(xml))
            {
                return null;
            }
            AlarmNotify notifyObject = Utils.GetNotifyObject<AlarmNotify>(xml);
            if (!((notifyObject != null) && this.ValidAlarmSign(notifyObject)))
            {
                return null;
            }
            return notifyObject;
        }

        public FeedBackNotify GetFeedBackNotify(Stream inStream)
        {
            string xml = this.ReadString(inStream);
            return this.GetFeedBackNotify(xml);
        }

        public FeedBackNotify GetFeedBackNotify(string xml)
        {
            if (string.IsNullOrEmpty(xml))
            {
                return null;
            }
            FeedBackNotify notifyObject = Utils.GetNotifyObject<FeedBackNotify>(xml);
            if (!((notifyObject != null) && this.ValidFeedbackSign(notifyObject)))
            {
                return null;
            }
            return notifyObject;
        }

        public PayNotify GetPayNotify(Stream inStream)
        {
            string xml = this.ReadString(inStream);
            return this.GetPayNotify(xml);
        }

        public PayNotify GetPayNotify(string xml)
        {
            if (string.IsNullOrEmpty(xml))
            {
                return null;
            }
            PayNotify notifyObject = Utils.GetNotifyObject<PayNotify>(xml);
            if (!((notifyObject != null) && this.ValidPaySign(notifyObject)))
            {
                return null;
            }
            PayInfo info = new PayInfo {
                SignType = UrlHelper.GetStringUrlParam("sign_type"),
                ServiceVersion = UrlHelper.GetStringUrlParam("service_version"),
                InputCharSet = UrlHelper.GetStringUrlParam("input_charset"),
                Sign = UrlHelper.GetStringUrlParam("sign"),
                SignKeyIndex = UrlHelper.GetIntUrlParam("sign_key_index"),
                TradeMode = UrlHelper.GetIntUrlParam("trade_mode"),
                TradeState = UrlHelper.GetIntUrlParam("trade_state"),
                Info = UrlHelper.GetStringUrlParam("pay_info"),
                Partner = UrlHelper.GetStringUrlParam("partner"),
                BankType = UrlHelper.GetStringUrlParam("bank_type"),
                BankBillNo = UrlHelper.GetStringUrlParam("bank_billno"),
                TotalFee = Convert.ToDecimal(UrlHelper.GetIntUrlParam("total_fee")) / 100M,
                FeeType = UrlHelper.GetIntUrlParam("fee_type"),
                NotifyId = UrlHelper.GetStringUrlParam("notify_id"),
                TransactionId = UrlHelper.GetStringUrlParam("transaction_id"),
                OutTradeNo = UrlHelper.GetStringUrlParam("out_trade_no"),
                Attach = UrlHelper.GetStringUrlParam("attach"),
                TransportFee = Convert.ToDecimal(UrlHelper.GetIntUrlParam("transport_fee")) / 100M,
                ProductFee = Convert.ToDecimal((int) (UrlHelper.GetIntUrlParam("product_fee") / 100)),
                Discount = Convert.ToDecimal(UrlHelper.GetIntUrlParam("discount")) / 100M,
                BuyerAlias = UrlHelper.GetStringUrlParam("buyer_alias")
            };
            notifyObject.PayInfo = info;
            return notifyObject;
        }

        private string ReadString(Stream inStream)
        {
            if (inStream == null)
            {
                return null;
            }
            byte[] buffer = new byte[inStream.Length];
            inStream.Read(buffer, 0, buffer.Length);
            return Encoding.UTF8.GetString(buffer);
        }

        public bool UpdateFeedback(string feedbackid, string openid)
        {
            string token = Utils.GetToken(this._payAccount.AppId, this._payAccount.AppSecret);
            return this.UpdateFeedback(feedbackid, openid, token);
        }

        public bool UpdateFeedback(string feedbackid, string openid, string token)
        {
            string url = string.Format("{0}?access_token={1}&openid={2}&feedbackid={3}", new object[] { Update_Feedback_Url, token, openid, feedbackid });
            string str2 = new WebUtils().DoGet(url);
            if (!(!string.IsNullOrEmpty(str2) && str2.Contains("ok")))
            {
                return false;
            }
            return true;
        }

        private bool ValidAlarmSign(AlarmNotify notify)
        {
            return true;
        }

        private bool ValidFeedbackSign(FeedBackNotify notify)
        {
            PayDictionary parameters = new PayDictionary();
            parameters.Add("appid", this._payAccount.AppId);
            parameters.Add("appkey", this._payAccount.PaySignKey);
            parameters.Add("timestamp", notify.TimeStamp);
            parameters.Add("openid", notify.OpenId);
            return (notify.AppSignature == SignHelper.SignPay(parameters));
        }

        private bool ValidPaySign(PayNotify notify)
        {
            PayDictionary parameters = new PayDictionary();
            parameters.Add("appid", this._payAccount.AppId);
            parameters.Add("appkey", this._payAccount.PaySignKey);
            parameters.Add("timestamp", notify.TimeStamp);
            parameters.Add("noncestr", notify.NonceStr);
            parameters.Add("openid", notify.OpenId);
            parameters.Add("issubscribe", notify.IsSubscribe ? 1 : 0);
            return (notify.AppSignature == SignHelper.SignPay(parameters));
        }
    }
}

